package com.atguigu.controller;


import com.atguigu.exception.SleepUtils;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 品牌表 前端控制器
 * </p>
 *
 * @author zhangqiang
 * @since 2021-12-28
 */
@RestController
public class RedissonController {
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 最简单的分布式锁
     *  1.redisson加的锁 默认有个30秒的过期时间(lockWatchdogTimeout=30s)
     *      不会出现死锁
     *  2.每隔10s就会自动续期
     *      internalLockLeaseTime / 3
     *      redisson的看门口狗机制
     */
    @GetMapping("lock")
    public String lock(){
        RLock lock = redissonClient.getLock("lock");
        //加锁 自旋等一会儿 一直等到拿锁成功 自动续期 默认用这个
        lock.lock();
        String uuid= UUID.randomUUID().toString();
        try {
            System.out.println(Thread.currentThread().getName()+"执行业务"+uuid);
            SleepUtils.sleep(5);
        } finally {
            lock.unlock();
        }
        return Thread.currentThread().getName()+":"+uuid;
    }

    @GetMapping("lock2")
    public String lock2(){
        RLock lock = redissonClient.getLock("lock");
        //10s过期 一般不用这种方式 不会有自动续期时间
        lock.lock(10, TimeUnit.SECONDS);
        String uuid= UUID.randomUUID().toString();
        try {
            SleepUtils.sleep(50);
            System.out.println(Thread.currentThread().getName()+"执行业务"+uuid);
        } finally {
            lock.unlock();
        }
        return Thread.currentThread().getName()+":"+uuid;
    }

    @GetMapping("lock3")
    public String lock3() throws Exception{
        RLock lock = redissonClient.getLock("lock");
        String uuid= UUID.randomUUID().toString();
        //lock.lock();
        try {
            //10s秒以内尝试拿锁，如果能拿到锁，给锁设置过期时间为35秒 获取不到就算了
            boolean accquireLock = lock.tryLock(10, 35, TimeUnit.SECONDS);
            if(accquireLock){
                System.out.println(Thread.currentThread().getName()+"执行业务"+uuid);
                SleepUtils.sleep(50);
            }
        } finally {
            lock.unlock();
        }
        return Thread.currentThread().getName()+":"+uuid;
    }

    private String message="hello";
    //写锁
    @GetMapping("write")
    public String write() throws Exception{
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("rwLock");
        RLock wLock = rwLock.writeLock();
        try {
           wLock.lock();
           message+=UUID.randomUUID().toString();
           SleepUtils.sleep(15);
        } finally {
            wLock.unlock();
        }
        return message;
    }

    //读锁
    @GetMapping("read")
    public String read() throws Exception{
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("rwLock");
        RLock rLock = rwLock.readLock();
        try {
            rLock.lock();
            return message;
        } finally {
            rLock.unlock();
        }
    }
    /**
     * 停车场 5个车位
     * a.占用车位
     * b.开走 释放车位
     */
    @GetMapping("/park")
    public String park() throws Exception{
        RSemaphore parkStation = redissonClient.getSemaphore("park_station");
        //信号量减1
        parkStation.acquire(1);
        System.out.println(Thread.currentThread().getName()+"找到车位");
        return Thread.currentThread().getName()+"找到车位";
    }
    @GetMapping("/left")
    public String left() throws Exception{
        RSemaphore parkStation = redissonClient.getSemaphore("park_station");
        //信号量加1
        parkStation.release(1);
        System.out.println(Thread.currentThread().getName()+"找到车位");
        return Thread.currentThread().getName()+"left";
    }


    @GetMapping("/ready")
    public String ready() throws Exception{
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("game");
        //数量减一
        countDownLatch.countDown();
        return Thread.currentThread().getName()+"就位";
    }
    @GetMapping("/start")
    public String start() throws Exception{
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("game");
        //设置需要多少资源
        countDownLatch.trySetCount(6);
        //等人来
        countDownLatch.await();
        return "大家一起去推塔";
    }





}

